﻿using System;
using System.Collections.Generic;
using Library.OrmEnterpriseEntity.Factor;
using Library.OrmEnterpriseEntity.TableInfo;

namespace Library.OrmEnterpriseEntity {
	///<summary>
	///</summary>
	public abstract class GlobalEntityView : TableView {
		protected abstract GlobalEntity CreateEntityInstance();
		protected sealed override DbTable CreateTableInstance() {
			return CreateEntityInstance();
		}
		///<summary>
		///</summary>
		///<returns></returns>
		public new GlobalEntity CreateInstance() {
			return CreateEntityInstance();
		}


		///<summary>
		///</summary>
		public const string RowIdName = "RowId";
		///<summary>
		///</summary>
		public const string SfuvcName = "Sfuvc";
		///<summary>
		///</summary>
		protected GlobalEntityView() {
			RowId = new Int64ColumnView(RowIdName, true, false, false, this);
			Sfuvc = AddInt16(SfuvcName, false, false);
		}
		///<summary>
		///</summary>
		public DbColumnView RowId { get; private set; }
		///<summary>
		///</summary>
		public DbColumnView Sfuvc { get; private set; }

		internal virtual DbColumnView ColumnRowType { get { return null; } }

		internal virtual QueryExpBuilder InnerExpression(QueryBuilder builder) {
			return null;
		}

		internal protected int ExcuteStatement(QueryStatement statement, int rowReturn) {
			int readed = 0;
			using (var reader = DbContext.Instance.Context.ExcuteStatement(new SelectStatementWrapper(statement) { RowReturn = rowReturn })) {
				var indexList = new List<Int32[]>();
				if (reader.Read()) {
					readed++;
					var values = new object[statement.SelectCols.Count];
					reader.GetValues(values);
					var ts = statement.Creator.CreateEntities();
					if (ts != null) {
						for (var j = 0; j < ts.Length; j++) {
							var t = ts[j];
							if (t == null) continue;
							var indexs = new List<Int32>();
							for (int i = 0; i < statement.SelectCols.Count; i++) {
								var retCol = statement.SelectCols[i];
								if (retCol.TableView.TableName == t.TableName) {
									indexs.Add(i);
								}
							}

							indexList.Add(indexs.ToArray());
							FillFromDb(values, statement.SelectCols, t, indexList[j]);
							statement.Creator.Commit(t);
						}
					}

					while (reader.Read()) {
						readed++;
						reader.GetValues(values);
						ts = statement.Creator.CreateEntities();
						if (ts != null) {
							for (var j = 0; j < ts.Length; j++) {
								var t = ts[j];
								if (t == null) continue;
								FillFromDb(values, statement.SelectCols, t, indexList[j]);
								statement.Creator.Commit(t);
							}
						}
					}
				}
				
				statement.Creator.CollectionComplete();
			}
			return readed;
		}

		internal virtual int ExcuteStatement(QueryStatement statement, int page, int pageSize) {

			if (page <= 0 || pageSize <= 0) {
				return 0;
			}
			using (var reader = DbContext.Instance.Context.ExcuteStatement(new SelectStatementWrapper(statement) { Page = page, PageSize = pageSize })) {
				int totalRows = 0;
				var indexList = new List<Int32[]>();
				if (reader.Read()) {
					var values = new object[reader.FieldCount];//[statement.SelectCols.Count];
					reader.GetValues(values);
					var ts = statement.Creator.CreateEntities();
					for (var j = 0; j < ts.Length; j++) {
						var t = ts[j];
						var indexs = new List<Int32>();
						for (int i = 0; i < statement.SelectCols.Count; i++) {
							var retCol = statement.SelectCols[i];
							if (retCol.TableView.TableName == t.TableName) {
								indexs.Add(i);
							}
						}

						indexList.Add(indexs.ToArray());
						FillFromDb(values, statement.SelectCols, t, indexList[j]);
						statement.Creator.Commit(t);

					}
					// last column is totalRow
					totalRows = Convert.ToInt32(values[values.Length - 1]);

					while (reader.Read()) {
						reader.GetValues(values);
						ts = statement.Creator.CreateEntities();
						for (var j = 0; j < ts.Length; j++) {
							var t = ts[j];
							FillFromDb(values, statement.SelectCols, t, indexList[j]);
							statement.Creator.Commit(t);
						}
					}
				}

				// relation creator

				return totalRows;
			}
		}

		protected static void FillFromDb(object[] reader, IList<DbColumnView> returnCols, DbTable entity, int[] entityColumnIndexs) {
			entity.BeginInit();
			foreach (var i in entityColumnIndexs) {
				var retCol = returnCols[i];
				var col = entity.Columns.Find(retCol.ColumnIndex);
				col.IntWriteFromDb(reader[i]);
			}

			entity.State = EntityState.DbNoChange;
			entity.EndInit();
		}

		///<summary>
		/// Get list of relation delete restrict
		///</summary>
		///<returns></returns>
		public virtual RelationView[] DeleteRestrict() {
			return null;
		}
		/// <summary>
		/// Get list of relation delete cascade
		/// </summary>
		/// <returns></returns>
		public virtual RelationView[] DeleteCascade() {
			return null;
		}
		/// <summary>
		/// Get list of parent table in relation ship
		/// </summary>
		/// <returns></returns>
		//public virtual RelationView[] Parents() {
		//  return null;
		//}
		/// <summary>
		/// 
		/// </summary>
		public virtual bool HasDeleteCascade {
			get { return DeleteCascade() != null; }
		}
		/// <summary>
		/// Table has delete contrain
		/// </summary>
		public virtual bool HasDeleteRestrict {
			get { return DeleteRestrict() != null; }
		}

		/// <summary>
		/// Create binding datasource
		/// </summary>
		/// <returns></returns>
		public virtual IOrmBindingList CreateBindingSource() {
			return null;
		}
	}
}
